<script lang="ts" setup>
import type { TableColumnCtx } from 'element-plus';

import { onMounted, ref } from 'vue';

import { VIcon } from '@croco/framework/icons';

import Sortable from 'sortablejs';

interface AuthProps {
    insert?: string;
    remove?: string;
    update?: string;
}

const props = withDefaults(
    defineProps<{
        auth?: AuthProps;
        columns: Array<TableColumnCtx>;
        dragSort?: boolean;
        formTemplate: any;
        placeholder?: string;
        primaryKey: string;
        submit?: (action: string, data: any) => Promise<void> | void;
    }>(),
    {
        auth: () => ({
            insert: 'none',
            remove: 'none',
            update: 'none',
        }),
        width: 120,
        placeholder: '暂无数据',
        dragSort: false,
        submit: () => Promise.resolve(),
    },
);

const datasource = defineModel<Array<any>>({ default: [] });

const tableRef = ref();
const editingRows = ref<Record<string, any>>({});
const sortableInstance = ref<null | Sortable>(null); // 用于保存 Sortable 实例

onMounted(() => {
    nextTick(() => {
        props.dragSort && initRowDrop();
    });
});

const initRowDrop = () => {
    // 获取表格的 tbody 元素。注意：el-table 渲染后的实际结构
    const tbody = tableRef.value.$el.querySelector('.el-table__body-wrapper tbody');
    if (sortableInstance.value) {
        sortableInstance.value.destroy(); // 初始化前先销毁旧实例，避免重复绑定
    }

    sortableInstance.value = Sortable.create(tbody, {
        handle: '.el-table__row',
        animation: 150, // 拖拽动画时长
        ghostClass: 'sortable-ghost',
        chosenClass: 'sortable-chosen',
        dragClass: 'sortable-drag',
        onEnd: (evt) => {
            // 拖拽结束事件：同步更新数据数组
            const { oldIndex, newIndex } = evt;
            const tableData = [...datasource.value];
            const currentRow = tableData.splice(oldIndex!!, 1)[0];
            tableData.splice(newIndex!!, 0, currentRow);
            datasource.value = tableData;
        },
    });
};

const handleAction = async (type: string, scope: any) => {
    const id = scope.row[props.primaryKey];
    switch (type) {
        case 'cancel': {
            Object.assign(scope.row, editingRows.value[id]);
            delete scope.row.editing;
            delete editingRows.value[id];
            break;
        }
        case 'edit': {
            editingRows.value[id] = { ...scope.row };
            scope.row.editing = true;
            break;
        }
        case 'remove': {
            props.submit('remove', scope);
            break;
        }
        case 'update': {
            props.submit('update', scope)!!.then(() => {
                delete scope.row.editing;
                delete editingRows.value[id];
            });
            break;
        }
        default: {
            props.submit('insert', scope);
            break;
        }
    }
};
</script>

<template>
    <el-table ref="tableRef" class="kt-form-table" :data="datasource" :row-key="primaryKey" border v-bind="$attrs">
        <el-table-column fixed="left" type="index" align="center" width="70">
            <template #header>
                <slot name="create">
                    <el-button v-auth="auth.insert" link @click="handleAction('add', { row: { ...formTemplate } })">
                        <template #icon>
                            <VIcon icon="icon:plus" />
                        </template>
                    </el-button>
                </slot>
            </template>
            <template #default="scope">
                <div class="kt-form-table__action">
                    <span>{{ scope.$index + 1 }}</span>
                    <div>
                        <slot name="action" :scope="scope">
                            <el-button v-if="!scope.row.editing" v-auth="auth.update" link type="primary" @click="handleAction('edit', scope)">
                                <template #icon>
                                    <VIcon icon="icon:edit-pen" />
                                </template>
                            </el-button>
                            <el-button v-if="!scope.row.editing" v-auth="auth.remove" link type="danger" @click="handleAction('remove', scope)">
                                <template #icon>
                                    <VIcon icon="icon:delete" />
                                </template>
                            </el-button>
                            <el-button v-if="scope.row.editing" v-auth="auth.update" link type="primary" @click="handleAction('update', scope)">
                                <template #icon>
                                    <VIcon icon="carbon:save" />
                                </template>
                            </el-button>
                            <el-button v-if="scope.row.editing" link type="danger" @click="handleAction('cancel', scope)">
                                <template #icon>
                                    <VIcon icon="icon:close" />
                                </template>
                            </el-button>
                        </slot>
                    </div>
                </div>
            </template>
        </el-table-column>
        <template v-for="column in columns" :key="column.prop">
            <el-table-column v-bind="column">
                <template #default="scope">
                    <el-input v-if="!$slots.hasOwnProperty(column.prop) && scope.row.editing" v-model="scope.row[column.prop]" clearable />
                    <slot v-else :name="column.prop" v-bind="scope">
                        {{ scope.row[column.prop] }}
                    </slot>
                </template>
            </el-table-column>
        </template>
        <template #empty>
            {{ placeholder }}
        </template>
    </el-table>
</template>

<style lang="scss" scoped>
.kt-form-table {
    width: 100%;

    :deep(tr) {
        background-color: unset;
    }

    .kt-form-table__action {
        text-align: center;

        span {
            display: inline-block;
        }

        div {
            display: none;
        }

        button + button {
            margin-left: 5px;
        }
    }

    .hover-row {
        .kt-form-table__action:has(button) {
            span {
                display: none;
            }

            div {
                display: inline-block;
            }
        }
    }
}
/* 被拖拽元素本身的样式 */
:deep(.sortable-chosen) {
    cursor: grabbing !important; /* 显示抓取状态的光标 */
    background-color: #f5f5f5 !important; /* 改变背景色以示选中 */
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); /* 添加阴影增强立体感 */
}

/* 拖拽过程中占位符（原位置）的样式 */
:deep(.sortable-ghost) {
    opacity: 0.6;
    background-color: #e6f7ff !important; /* 浅蓝色背景作为占位提示 */
}

/* 正在被拖拽的元素的样式（可选，用于更复杂的效果） */
:deep(.sortable-drag) {
    cursor: grabbing !important;
    transform: rotate(5deg); /* 可添加轻微旋转等效果 */
}
</style>
